package com.plian.system.controller.transfer;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.plian.Tools.CollectionUtil;
import com.plian.system.config.AppKeySign;
import com.plian.system.dto.transfer.IndicatorSign;
import com.plian.system.entity.fr.bank.BankKey;
import com.plian.system.entity.im.*;
import com.plian.system.entity.sys.Org;
import com.plian.system.model.R;
import com.plian.system.model.token.PassToken;
import com.plian.system.service.fr.bank.IBankKeyService;
import com.plian.system.service.im.*;
import com.plian.system.service.sys.orgzation.IOrgService;
import com.plian.system.service.transfer.IInvestmentTransferService;
import com.plian.system.vo.im.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

@RestController
@RequestMapping(value = "api/investmenttransfer")
@Api(value = "项目投资数据对接", tags = "项目投资数据对接")
@Slf4j
public class InvestmentTransferController {

    @Autowired
    private IInvestmentTransferService investmentTransferService;

    @Autowired
    private IBankKeyService bankKeyService;

    @Autowired
    private IOrgService orgService;

    @Autowired
    private IBaseInvestmentPlanService baseInvestmentPlanService;

    @Autowired
    private IBaseInvestmentExecutionService investmentExecutionService;

    @Autowired
    private IFixedInvestmentPlanService fixedInvestmentPlanService;

    @Autowired
    private IStakeInvestmentPlanService stakeInvestmentPlanService;

    @Autowired
    private IEffectiveInvestmentService effectiveInvestmentService;

    @Autowired
    private IMainProjectSituationService mainProjectSituationService;

    @Autowired
    private IExecutionProjectSituationService projectSituationService;


    @PostMapping(value = "/submit-project-list")
    @ApiOperation(value = "投资项目信息 批量", notes = "传入projectInfoVOS")
    public R submitProjectList(@RequestBody List<ProjectInfoVO> projectInfoVOS){
        return investmentTransferService.submitProjectList(projectInfoVOS);
    }

    @PostMapping(value = "/submit-fund-project-list")
    @ApiOperation(value = "投资基金项目信息 批量", notes = "传入fundProjectInfoVOS")
    public R submitFundProjectList(@RequestBody List<FundProjectInfoVO> fundProjectInfoVOS){
        return investmentTransferService.submitFundProjectList(fundProjectInfoVOS);
    }

    @PostMapping(value = "/submit-plan-list")
    @ApiOperation(value = "项目投资计划 批量", notes = "传入baseInvestmentPlanVOS")
    public R submitPlanList(@RequestBody List<BaseInvestmentPlanVO> baseInvestmentPlanVOS){
        return investmentTransferService.submitPlanList(baseInvestmentPlanVOS);
    }

    @PostMapping(value = "/submit-execution-list")
    @ApiOperation(value = "项目投资计划执行 批量", notes = "传入baseInvestmentExecutionVOS")
    public R submitExecutionList(@RequestBody List<BaseInvestmentExecutionVO> baseInvestmentExecutionVOS){
        return investmentTransferService.submitExecutionList(baseInvestmentExecutionVOS);
    }

    @PostMapping(value = "/submit-fund-execution-list")
    @ApiOperation(value = "基金项目执行 批量", notes = "传入fundProjectExecutionVOS")
    public R submitFundExecutionList(@RequestBody List<FundProjectExecutionVO> fundProjectExecutionVOS){
        return investmentTransferService.submitFundExecutionList(fundProjectExecutionVOS);
    }

    /**
     * 提供时间段内的 项目投资计划 信息
     * @param indicatorSign
     */
    @PostMapping(value = "/investment-plan-time")
    @PassToken
    @AppKeySign
    public R<List<BaseInvestmentPlan>> getInvestmentByTime(@RequestBody IndicatorSign indicatorSign){
        log.debug("toklen:" + indicatorSign.getToken());
        String appId = indicatorSign.getAppId();
        BankKey bankKey = bankKeyService.getOne(Wrappers.<BankKey>lambdaQuery().eq(BankKey::getAppId, appId));
        String topGroupId = bankKey.getTopGroupId();
        List<Org> allChild = orgService.getAllChild(topGroupId);
        List<String> orgIds = allChild.stream().map(Org::getId).collect(Collectors.toList());
        List<BaseInvestmentPlan> list = baseInvestmentPlanService.list(new LambdaQueryWrapper<BaseInvestmentPlan>().in(BaseInvestmentPlan::getCreateCompanyId, orgIds)
                .eq(Optional.ofNullable(indicatorSign.getYear()).isPresent(), BaseInvestmentPlan::getFilingYear, indicatorSign.getYear())
                        .eq(BaseInvestmentPlan::getStatus,3)
                );
        if (CollectionUtil.isNotEmpty(list)){
            List<Long> baseIds = list.stream().map(BaseInvestmentPlan::getId).collect(Collectors.toList());
            List<FixedInvestmentPlan> fixedInvestmentPlanList = fixedInvestmentPlanService.list(new LambdaQueryWrapper<FixedInvestmentPlan>().in(FixedInvestmentPlan::getBaseInvestmentPlanId, baseIds));
            if (CollectionUtil.isNotEmpty(fixedInvestmentPlanList)){
                Map<Long, List<FixedInvestmentPlan>> mapFixed = fixedInvestmentPlanList.stream().collect(Collectors.groupingBy(FixedInvestmentPlan::getBaseInvestmentPlanId));
                list.forEach(plan ->{
                    plan.setFixedInvestmentPlans(mapFixed.get(plan.getId()));
                });
            }

            List<StakeInvestmentPlan> stakeInvestmentPlans = stakeInvestmentPlanService.list(new LambdaQueryWrapper<StakeInvestmentPlan>().in(StakeInvestmentPlan::getBaseInvestmentPlanId, baseIds));
            if (CollectionUtil.isNotEmpty(stakeInvestmentPlans)){
                Map<Long, List<StakeInvestmentPlan>> mapByStake = stakeInvestmentPlans.stream().collect(Collectors.groupingBy(StakeInvestmentPlan::getBaseInvestmentPlanId));
                list.forEach(plan ->{
                    plan.setStakeInvestmentPlans(mapByStake.get(plan.getId()));
                });
            }
        }
        return R.data(list);
    }

    /**
     * 提供时间段内的 项目投资计划执行 信息
     * @param indicatorSign
     */
    @PostMapping(value = "/investment-execution-time")
    @PassToken
    @AppKeySign
    public R<List<BaseInvestmentExecution>> getInvestmentExecutionByTime(@RequestBody IndicatorSign indicatorSign){
        log.debug("toklen:" + indicatorSign.getToken());
        String appId = indicatorSign.getAppId();
        BankKey bankKey = bankKeyService.getOne(Wrappers.<BankKey>lambdaQuery().eq(BankKey::getAppId, appId));
        String topGroupId = bankKey.getTopGroupId();
        List<Org> allChild = orgService.getAllChild(topGroupId);
        List<String> orgIds = allChild.stream().map(Org::getId).collect(Collectors.toList());
        LambdaQueryWrapper<BaseInvestmentExecution> queryWrapper = new LambdaQueryWrapper<BaseInvestmentExecution>().in(BaseInvestmentExecution::getCreateCompanyId, orgIds)
                .eq(BaseInvestmentExecution::getStatus, 3);
        if (Optional.ofNullable(indicatorSign.getMonth()).isPresent()){
            String month = indicatorSign.getYear() + "-" + indicatorSign.getMonth();
            queryWrapper.eq(BaseInvestmentExecution::getFilingMonth, month);
        }
        List<BaseInvestmentExecution> list = investmentExecutionService.list(queryWrapper);

        if (CollectionUtil.isNotEmpty(list)){
            List<Long> baseIds = list.stream().map(BaseInvestmentExecution::getId).collect(Collectors.toList());
            List<EffectiveInvestment> effectiveInvestments = effectiveInvestmentService.list(new LambdaQueryWrapper<EffectiveInvestment>().in(EffectiveInvestment::getBaseInvestmentExecutionId, baseIds));
            if (CollectionUtil.isNotEmpty(effectiveInvestments)){
                List<Long> effIds = effectiveInvestments.stream().map(EffectiveInvestment::getId).collect(Collectors.toList());
                List<MainProjectSituation> mainProjectSituations = mainProjectSituationService.list(new LambdaQueryWrapper<MainProjectSituation>().in(MainProjectSituation::getEffectiveInvestmentId, effIds));
                if (CollectionUtil.isNotEmpty(mainProjectSituations)){
                    Map<Long, List<MainProjectSituation>> map = mainProjectSituations.stream().collect(Collectors.groupingBy(MainProjectSituation::getEffectiveInvestmentId));
                    effectiveInvestments.forEach(plan ->{
                        plan.setMainProjectSituations(map.get(plan.getId()));
                    });
                }
                List<ExecutionProjectSituation> stakeProjects = projectSituationService.list(new LambdaQueryWrapper<ExecutionProjectSituation>().in(ExecutionProjectSituation::getEffectiveInvestmentId, effIds).eq(ExecutionProjectSituation::getProjectType, 1));
                if (CollectionUtil.isNotEmpty(stakeProjects)){
                    Map<Long, List<ExecutionProjectSituation>> map = stakeProjects.stream().collect(Collectors.groupingBy(ExecutionProjectSituation::getEffectiveInvestmentId));
                    effectiveInvestments.forEach(plan ->{
                        plan.setStakeProjectSituations(map.get(plan.getId()));
                    });
                }
                List<ExecutionProjectSituation> fixedProjects = projectSituationService.list(new LambdaQueryWrapper<ExecutionProjectSituation>().in(ExecutionProjectSituation::getEffectiveInvestmentId, effIds).eq(ExecutionProjectSituation::getProjectType, 2));
                if (CollectionUtil.isNotEmpty(fixedProjects)){
                    Map<Long, List<ExecutionProjectSituation>> map = fixedProjects.stream().collect(Collectors.groupingBy(ExecutionProjectSituation::getEffectiveInvestmentId));
                    effectiveInvestments.forEach(plan ->{
                        plan.setFixedProjectSituations(map.get(plan.getId()));
                    });
                }
                Map<Long, List<EffectiveInvestment>> effetMap = effectiveInvestments.stream().collect(Collectors.groupingBy(EffectiveInvestment::getBaseInvestmentExecutionId));
                list.forEach(execution -> {
                    List<EffectiveInvestment> investments = effetMap.get(execution.getId());
                    if (CollectionUtil.isNotEmpty(investments)){
                        execution.setEffectiveInvestment(investments.get(0));
                    }
                });
            }
        }
        return R.data(list);
    }

}
